package com.om.abom.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.om.abom.entity.AppServerEntity;
import com.om.abom.entity.UpgradeRecordEntity;
import com.om.abom.mapper.UpgradeRecordMapper;
import com.om.abom.service.AppServerService;
import com.om.abom.service.UpgradeRecordService;
import com.om.abom.utils.JschExecutor;
import com.om.abom.utils.ScpClientUtil;
import com.om.abom.ws.SocketSendMessageHelp;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.socket.WebSocketSession;

import java.io.IOException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

import static com.om.abom.utils.JschExecutor.execMultiCmd;
import static com.om.abom.utils.ProcessManagement.processStart;
import static com.om.abom.utils.ProcessManagement.processStop;


@Slf4j
@Service("upgradeRecordService")
public class UpgradeRecordServiceImpl extends ServiceImpl<UpgradeRecordMapper, UpgradeRecordEntity> implements UpgradeRecordService
{
    @Autowired
    AppServerService appServerService;

    @Override
    public void upgrade(long id, WebSocketSession session) throws IOException
    {
        SocketSendMessageHelp socketSendMessageHelp = new SocketSendMessageHelp(session);

        String errorMsg = upgrade(id, socketSendMessageHelp);

        if (errorMsg != null) {
            socketSendMessageHelp.sendErrorMsg(errorMsg);
        }

        session.close();
    }

    public String upgrade(long id, SocketSendMessageHelp socketSendMessageHelp)
    {
        AppServerEntity appServer = appServerService.getById(id);
        String hostIp = appServer.getHostIp();
        log.warn("update host {}", hostIp);
        return execMultiCmd(hostIp, executor -> {
            try {
                return doUpgrade(executor, appServer, socketSendMessageHelp);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        });
    }

    private String doUpgrade(JschExecutor executor, AppServerEntity appServer, SocketSendMessageHelp msgHelp) throws Exception
    {
        String serverName = appServer.getServerName();
        LocalDateTime upgradeTime = LocalDateTime.now();

        String errorMsg = backup(serverName, executor, msgHelp, upgradeTime);
        if (errorMsg != null) {
            return errorMsg;
        }

        // 更新 jar 包
        ScpClientUtil scpClient = new ScpClientUtil(executor.getIp());
        scpClient.putFile(
                "E:/code/anbang/omPlatform/abom/target/abom-0.0.1-SNAPSHOT.jar",
                "/root/"
        );
        String msg = "jar 包更新完成";
        msgHelp.sendInfoMsg(msg);
        log.warn(msg);

        // 启动更新好的 jar 包
        errorMsg = processStart(executor);
        if ("启动失败".equals(errorMsg)) {
            return errorMsg;
        }

        // 新增更新记录
        UpgradeRecordEntity upgradeRecordEntity = new UpgradeRecordEntity();
        upgradeRecordEntity.setUpgradeType(1);  // 设置更新记录的类型为备份
        upgradeRecordEntity.setBackupPath(upgradeTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd_HH-mm-ss")));
        upgradeRecordEntity.setBackupServer(appServer.getId());
        upgradeRecordEntity.setUpgradeTime(upgradeTime);
        this.save(upgradeRecordEntity);

        appServer.setServerLatestUpdateTime(upgradeTime);
        appServerService.updateById(appServer);

        msg = String.format("%s 服务更新完成", serverName);
        msgHelp.sendSuccessMsg(msg);
        log.warn(msg);
        return null;
    }

    public String backup(String serverName,
                         JschExecutor executor, SocketSendMessageHelp msgHelp,
                         LocalDateTime upgradeTime
    ) throws Exception
    {
        String msg;
        // 停止服务
        String errorMsg = processStop(executor);
        if ("停止失败".equals(errorMsg)) {
            return errorMsg;
        } else if (errorMsg == null) {
            msg = String.format("停止 %s 服务成功", serverName);
        } else {
            msg = String.format("%s 服务没有在运行", serverName);
        }
        msgHelp.sendInfoMsg(msg);
        log.warn(msg);

        // 备份
        String backupPath = "/opt/" + upgradeTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd_HH-mm-ss"));
        executor.execCmd("mkdir " + backupPath);
        String cmd_backup = "mv /root/abom-0.0.1-SNAPSHOT.jar " + backupPath;
        executor.execCmd(cmd_backup);
        msg = String.format("%s 服务备份到了 %s", serverName, backupPath);
        msgHelp.sendInfoMsg(msg);
        log.warn(msg);
        return null;
    }

    @Override
    public void restore(long backupRecordId, WebSocketSession session) throws IOException
    {
        SocketSendMessageHelp socketSendMessageHelp = new SocketSendMessageHelp(session);

        String errorMsg = restore(backupRecordId, socketSendMessageHelp);

        if (errorMsg != null) {
            socketSendMessageHelp.sendErrorMsg(errorMsg);
        }

        session.close();
    }

    public String restore(long backupRecordId, SocketSendMessageHelp socketSendMessageHelp)
    {
        UpgradeRecordEntity upgradeRecord = getById(backupRecordId);

        AppServerEntity appServer = appServerService.getById(upgradeRecord.getBackupServer());

        log.warn("restore backupRecordId {}", backupRecordId);
        return execMultiCmd(appServer.getHostIp(), executor -> {
            try {
                return doRestore(executor, upgradeRecord, appServer, socketSendMessageHelp);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        });
    }

    private String doRestore(JschExecutor executor,
                             UpgradeRecordEntity backupRecord, AppServerEntity appServer,
                             SocketSendMessageHelp msgHelp
    ) throws Exception
    {
        String serverName = appServer.getServerName();
        LocalDateTime upgradeTime = LocalDateTime.now();

        String errorMsg = backup(serverName, executor, msgHelp, upgradeTime);
        if (errorMsg != null) {
            return errorMsg;
        }

        // 还原
        String backupPath1 = backupRecord.getBackupPath();
        String cmd_restore = "mv /opt/" + backupPath1 + "/abom-0.0.1-SNAPSHOT.jar /root/";
        executor.execCmd(cmd_restore);
        executor.execCmd("rm -rf /opt/" + backupPath1);
        String msg = "jar 包还原完成";
        msgHelp.sendInfoMsg(msg);
        log.warn(msg);

        // 启动还原的 jar 包
        errorMsg = processStart(executor);
        if ("启动失败".equals(errorMsg)) {
            return errorMsg;
        }
        msg = "服务启动成功";
        msgHelp.sendInfoMsg(msg);
        log.warn(msg);

        // 新增还原记录
        UpgradeRecordEntity upgradeRecordEntity = new UpgradeRecordEntity();
        upgradeRecordEntity.setUpgradeType(2);  // 更新记录的类型为还原
        upgradeRecordEntity.setBackupPath(upgradeTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd_HH-mm-ss")));
        upgradeRecordEntity.setBackupServer(appServer.getId());
        upgradeRecordEntity.setUpgradeTime(upgradeTime);
        upgradeRecordEntity.setUpgradeRecordIdForRestoreRecord(backupRecord.getId());   // 设置备份记录的 id
        this.save(upgradeRecordEntity);

        backupRecord.setRestoreRecordId(upgradeRecordEntity.getId());   // 设置还原记录的 id
        this.updateById(backupRecord);

        appServer.setServerLatestUpdateTime(upgradeTime);
        appServerService.updateById(appServer);

        msg = String.format("%s 服务还原完成", serverName);
        msgHelp.sendSuccessMsg(msg);
        log.warn(msg);
        return null;
    }
}